package com.jzo2o.foundations.service.impl;

import cn.hutool.core.bean.BeanUtil;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.common.utils.StringUtils;
import com.jzo2o.es.core.ElasticSearchTemplate;
import com.jzo2o.es.utils.SearchResponseUtils;
import com.jzo2o.foundations.model.domain.ServeAggregation;
import com.jzo2o.foundations.model.dto.response.ServeSimpleResDTO;
import com.jzo2o.foundations.service.ServeAggregationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 服务搜索实现类
 */
@Service
@Slf4j
public class ServeAggregationServiceImpl implements ServeAggregationService {
    @Resource
    private ElasticSearchTemplate elasticSearchTemplate;

    /**
     * GET /serve_aggregation/_search
     * {"query": {
     *     "bool": {
     *       "must": [
     *         {
     *           "term": {
     *             "serve_type_id": {
     *             "value": 1970475490699411458
     *             }
     *           }
     *         },
     *         {
     *           "term": {
     *             "city_code": {
     *               "value": "0371"
     *             }
     *           }
     *         },
     *         {
     *           "multi_match": {
     *             "query": "测试",
     *             "fields": ["serve_item_name","serve_type_name"]
     *           }
     *         }
     *       ]
     *     }
     *   },
     *   "sort": [
     *     {
     *       "serve_item_sort_num": {
     *         "order": "asc"
     *       }
     *     }
     *   ]
     * }
     */
    // 所需的ES语句

    /**
     * 用户端 - 首页服务搜索
     * 搜索条件：城市编码、服务类型id、关键词
     */
    @Override
    public List<ServeSimpleResDTO> findServeList(String cityCode, Long serveTypeId, String keyword) {
        // 构建查询请求
        SearchRequest.Builder builder = new SearchRequest.Builder();

        // 拼装查询条件
        builder.query(query -> query.bool(bool -> {
            // 根据城市编码查询
            bool.must(must ->
                    must.term(term -> term.field("city_code").value(cityCode)));
            // 根据服务类型id查询
            if (ObjectUtils.isNotEmpty(serveTypeId)) {
                bool.must(must ->
                        must.term(term ->
                                term.field("serve_type_id").value(serveTypeId)));
            }
            // 根据关键词查询
            if (StringUtils.isNotBlank(keyword)) {
                // 多字段匹配
                bool.must(must -> must.multiMatch(multiMatch -> multiMatch.query(keyword).fields("serve_item_name", "serve_type_name")));
            }
            return bool;
        }));

        List<SortOptions> sortOptionsList = new ArrayList<>();
        // 添加一个排序字段
        sortOptionsList.add(SortOptions.of(sortOptions -> sortOptions.field(field -> field.field("serve_item_sort_num").order(SortOrder.Asc))));
        builder.sort(sortOptionsList);
        // 设置索引
        builder.index("serve_aggregation");
        // 构建查询条件结束，并获得SearchRequest请求对象
        SearchRequest searchRequest = builder.build();

        // 执行es检索数据
        SearchResponse<ServeAggregation> searchResponse = elasticSearchTemplate.opsForDoc().search(searchRequest, ServeAggregation.class);
        // 如果搜索成功返回结果集
        if (SearchResponseUtils.isSuccess(searchResponse)) {
            //获取查询结果：searchResponse.hits().hits() 用于获取 Elasticsearch 查询返回的所有命中（匹配）的文档集合，返回的是一个Hit对象数组。
            List<ServeAggregation> collect = searchResponse.hits().hits().stream()
                    //对流中的每个Hit对象进行转换
                    .map(item -> {
                        ServeAggregation source = item.source();
                        return source;
                    }).collect(Collectors.toList()); //收集结果：.collect(Collectors.toList()) 将流中的所有ServeAggregation对象收集起来，形成一个List<ServeAggregation>集合。
            // 将结果集返回
            // 将collect转成List<ServeSimpleResDTO>类型
            List<ServeSimpleResDTO> serveSimpleResDTOS = BeanUtils.copyToList(collect, ServeSimpleResDTO.class);
            return serveSimpleResDTOS;
        }
        return Collections.emptyList();
    }

}
